#ifndef AUTOPOINTER_H
#define AUTOPOINTER_H

/*template<class T> class AutoPointer {
public:
	explicit AutoPointer(T* _ptr) : ptr(_ptr) { }
	explicit AutoPointer() : ptr(0) { }

	AutoPointer(const AutoPointer<T>& toCopy) {
		if (toCopy.ptr) ptr = toCopy.ptr->clone();
		else ptr = 0;
	}

	AutoPointer<T>& operator=(const AutoPointer<T>& toCopy) {
		if (ptr) {
			delete ptr;
		}
		if (toCopy.ptr) ptr = toCopy.ptr->clone();//TODO segmentation fault
		return *this;
	}

	~AutoPointer() {
		if (ptr) {
			delete ptr;
			ptr = 0;
		}
	}

	T* operator->() const {
		return ptr;
	}

	T& operator*() const {
		return *ptr;
	}

	T* get() const { return ptr; }

	void set(T* _ptr) {
		ptr = _ptr;
	}

	bool isNull() const { return ptr == 0; }

private:
	T* ptr;
};*/

template <class T> class AutoPointer {
public:
	explicit AutoPointer(T* p = 0) {
		if (p) data = new Data(p);
		else data = 0;
	}

	AutoPointer(const AutoPointer& snd) {
		acquire(snd.data);
	}

	AutoPointer& operator=(const AutoPointer& r) {
		if (this != &r) {
			release();
			acquire(r.data);
		}
		return *this;
	}

	~AutoPointer() {
		release();
	}

	T* operator->() const {
		return data->ptr;
	}

	T& operator*() const {
		return *data->ptr;
	}

	/*void set(T* p) {
		if (data) {
			delete data->prt;
			data->ptr = p;
		}
		else {
			data = new Data(p);
		}
	}*/

	T* get() const { return data ? data->ptr : 0; }

	bool isNull() const { return data ? data->ptr == 0 : true; }

	void set(T* _ptr) {
		release();
		data = new Data(_ptr);
	}

private:
	struct Data {
		Data(T* p = 0, unsigned int _counter = 1) : ptr(p), counter(_counter) { }
		T* ptr;
		unsigned int counter;
	}* data;

	void acquire(Data* c) {
		data = c;
		if (c) ++c->counter;
	}

	void release() {
		if (data) {
			if (--data->counter == 0) {
				delete data->ptr;
				delete data;
			}
			data = 0;//TODO why here?
		}
	}
};

#endif
